/*
 * Copyright 2025 LinQingYing. and contributors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * The use of this source code is governed by the Apache License 2.0,
 * which allows users to freely use, modify, and distribute the code,
 * provided they adhere to the terms of the license.
 *
 * The software is provided "as-is", and the authors are not responsible for
 * any damages or issues arising from its use.
 *
 */

package org.cangnova.cangjie.types

enum class EnrichedProjectionKind {
    IN, OUT, INV, STAR;

    companion object {
        @JvmStatic
        fun fromVariance(variance: Variance): EnrichedProjectionKind {
            return when (variance) {
                Variance.INVARIANT -> INV

            }
        }

        // If class C<out T> then C<T> and C<out T> mean the same
        // out * out = out
        // out * in  = *
        // out * inv = out
        //
        // in * out  = *
        // in * in   = in
        // in * inv  = in
        //
        // inv * out = out
        // inv * in  = out
        // inv * inv = inv
        fun getEffectiveProjectionKind(
            typeParameterVariance: Variance,
            typeArgumentVariance: Variance
        ): EnrichedProjectionKind {
            var a = typeParameterVariance
            var b = typeArgumentVariance

            // If they are not both invariant, let's make b not invariant for sure
            if (b === Variance.INVARIANT) {
                val t = a
                a = b
                b = t
            }


           return fromVariance(b)

            // If they are not opposite, return b, because b is either equal to a or b is in/out and a is inv
        }
    }
}


